/*
*   向服务器发送数据请求的方案
*       第一类：XMLHttpRequest
*           + ajax      自己编写请求的逻辑
*           + axios     第三方库，对XMLHttpRequest 进行封装[基于promise封装]
*       第二类：fetch       - 不兼容 IE
*           + ES6 内置的API，本身既是基于 promise，用全新的方案实现客户端喝服务器的数据请求
*           + 机制的完善度上，不如 XMLHttpRequest 的(例如：无法设置超时时间，没有内置的请求中断处理...)
*       第三类：其他方案，主要是跨域为主
*           + jsonp
*           + postMessage
*           + 利用img的src发送请求，实现数据埋点(用途：用户在这个页面停留的时间)和上报(用途：哪些页面用户点击较多)
* */

//      + 在客户端和服务器通信中，只要客户端设置了cookie，在每一次请求时，默认会在请求头中，基于cookie字段，把本地的cookie信息传递给服务器
// let promise实例 = fetch(请求地址，配置项)
//      + fulfilled 成功   rejected 失败
//      + fetch 和 axios 有一个不一样的地方，在fetch中，只要服务器有反馈信息(无论状态码是什么)，都说明请求成功，最后的实例都是fulfilled
//      + 只有服务器没有任何响应(例如：请求中断，超时，断网...)，实例才是 rejected
//      + 在 axios中，只有返回状态码是2开头的，才会让实例是成功态

//  配置项
//      + method    请求的方式，默认为 (*get, head, delete, options ,post, put, patch)
//      + mode      请求的模式   no-cors,*cors,same-origin
//      + cache     缓存模式    (*default, no-cache, reload, force-cache, only-if-cached)
//      + credentials   资源凭证    (include, *same-origin, omit)
//          fetch情况下，跨域请求中，是不允许携带资源凭证的，只有同源下才允许
//          include：同源和跨域下都可以
//          same-origin:只有同源下可以
//          omit：都不可以
//      + headers:普通对象 {} / Headrs实例
//          自定义请求头信息
//      + body: 设置请求主体信息
//          只适用于post系列请求，在其他请求中设置回报错(让返回的实例变成失败态)
//          body 设置的格式有要求的,并要指定 Content-Type 请求头信息
//              JSON字符串     '{"name":"aa"}'
//              URLENCODED字符串       'xxx=xxx&xxx=xxx'
//              普通字符串   text/plain
//              FormData对象          multipart/form-data
//                  主要运用在文件上传(或者表单提交)的操作中！！！    let fm = new FormData()  fm.append('file',文件)
//          二进制或者Buffer格式
//

// 我们发现，相比较于 axios，fetch没有对get请求，问号传参的信息做特殊处理(axios 基于params设置问号传参信息)，需要自己手动拼接到URL末尾才行

/*  Headers类：头处理类(请求头或响应头)
*       Headers.prototype
*           + append    新增头信息
*           + delete    删除头信息
*           + forEach   迭代所有头信息
*           + get       获取某一项的信息
*           + has       验证是否包含某一项
* */
import qs from "qs";
import {message} from 'antd'
import http from "@/api/http2.js"

let head = new Headers()
head.append('Content-Type', 'application/json')
head.append("name", 'liuk')
head.forEach((item, i) => {
    console.log(item, i)
})
console.log(head.get('Content-Type'))
console.log(head.has('Content-Type'))
console.log(head, '头处理类')

/*
*  服务器返回的 response对象(Response实例)
*       私有属性：
*           + body  响应式主体信息(他是一个 ReadableStream 可读流)，处理
*           + headers   响应头信息(他是headers类的实例)
*           + status / statusText   返回的http状态码及描述
*       response.prototype
*           + arrayBuffer
*           + blob
*           + formData
*           + json
*           + text
*           ...  这些方法用来处理 body 可读流信息，把可读流转换为我们自己需要的格式,
*           ...  返回 一个 promise实例，避免服务器在转换中出现问题(比如服务器返回流文件，转化为json对象，返回失败的实例)
*
* */

let p = fetch('/api/getTaskList2', {
    headers: head
}).then(response => {
    // 进入 then 中的时候，不一定是请求成功(因为状态码可能是各种情况)
    let {headers, status, statusText} = response
    if (/^(2|3\d{2}$)/.test(status)) {
        console.log('成功', response.body)
        console.log('服务器时间', headers.get('Date'))
        return response.json(response.body)
    }
    // 获取数据失败的
    return Promise.reject({
        code: -100,
        status,
        statusText
    })
}).then(value => {
    console.log(value)
}).catch(reason => {
    // 会有不同的失败情况
    // 1. 服务器没有返回任何值
    // 2. 状态码不对
    // 3. 数据转换失败
    console.log('失败', reason)
})


document.body.addEventListener('click', function () {
    fetch('/api/addTask', {
        method: 'POST',
        // 设置请求头
        headers: {
            "Content-Type": "application/x-www-form-urlencoded"
        },
        // 自己手动把请求格式变为服务器需要的
        body: qs.stringify({
            task: "我学会了Fetch的操作",
            time: "2022-12-15 12:00:00"
        }),
    }).then(response => {
        let {status, statusText} = response
        if (/^(2|3\d{2}$)/.test(status)) {
            return response.json(response.body)
        }
        // 获取数据失败的
        return Promise.reject({
            code: -100,
            status,
            statusText
        })
    }).then(value => {
        console.log("最终处理结果", value)
    }).catch(reason => {
        message.error('请求失败')
        console.log('失败', reason)
    })
})

// axios 中我们设置一个普通对象，axios内部会把期变成json字符串传递给服务器

/* fetch 的请求中断 */
let ctrol = new AbortController()
fetch('/api/getTaskList', {
    // 请求中断信号
    signal: ctrol.signal
}).then(response => {
    let {status, statusText} = response
    if (/^(2|3\d{2}$)/.test(status)) {
        return response.json(response.body)
    }
    // 获取数据失败的
    return Promise.reject({
        code: -100,
        status,
        statusText
    })
}).then(value => {
    console.log("最终处理结果", value)
}).catch(reason => {
    message.error('请求失败')
    console.log('失败', reason)
})
// 立即中断请求
// ctrol.abort()


// ---------------------------------
// console.log(http,221231,'哇啊')
http.get('/api/getTaskList', {
    params: {
        state: 2
    }
}).then(value => {
    console.log('成功:', value)
})

document.body.addEventListener('keydown', function () {
    http.post('/api/addTask', {
        body: {
            task: "我学会了Fetch的操作(包括封装)",
            time: "2022-12-15 12:00:00"
        }
    }).then(value => {
        console.log("最终处理结果", value)
    })
})
